#include "DeviceInformation.h"

#include <fstream>
#include <iostream>
#include <sstream>
#include <map>
#include <algorithm>

using namespace std;

map<string, string> VID_MAP;
map<string, string> PID_MAP;

void MapDeviceVidsPids(const char *filename);

DeviceInformation::DeviceInformation(std::wstring deviceType_, WCHAR* devId, bool addObserved)
{
	WCHAR wcNumber[4];
	MapDeviceVidsPids("usb.txt");
	//string wcNumber("08ec");
	bIsListened = addObserved;

	deviceType = deviceType_;

	ostringstream stm;

	string vid, pid;


	mystrcpy(devId, deviceId, wcslen(devId));

	mystrcpy(deviceId + 8, wcNumber, 4);
	vid = WcharToString(wcNumber, 4);
	
	transform(vid.begin(), vid.end(), vid.begin(), tolower);
	
	stm << "0x" << vid;
	vendorName = VID_MAP[vid];
	if (!vendorName.compare(string("")))
	{
		stm << " (unknown)";
	}
	else
	{
		stm << " (" << vendorName << ")";
	}
	vendorName = stm.str();

	stm.str("");

	mystrcpy(deviceId + 17, wcNumber, 4);
	pid = WcharToString(wcNumber, 4);
	stm << "0x" << pid;

	transform(pid.begin(), pid.end(), pid.begin(), tolower);
	
	deviceName = PID_MAP[vid+pid];
	if (!deviceName.compare(string("")))
	{
		stm << " (unknown)";
	}
	else
	{
		stm << " (" << deviceName << ")";
	}
	deviceName = stm.str();	
}

void DeviceInformation::mystrcpy(const WCHAR* source, WCHAR* destination, unsigned int count)
{
	unsigned i;
	for (i = 0; i < count; i++)
	{
		destination[i] = source[i];
	}
}

std::wstring DeviceInformation::GetDeviceType()
{
	return deviceType;
}


std::string DeviceInformation::GetDevName()
{
	return deviceName;
}

std::string DeviceInformation::GetVendorName()
{
	return vendorName;
}

std::string DeviceInformation::isListened()
{
	return bIsListened ? std::string("YES") : std::string("NO");
}

void DeviceInformation::StartListen()
{
	DWORD dwWaitResult;
	HANDLE hDevice = CreateFile(CONTROL_DEVICE_DOS_NAME, 0, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);

	if(hDevice == INVALID_HANDLE_VALUE)
	{
		cout<<"INAVALID_HANDLE_FILE::startListen";
	}

	DeviceIoControl(hDevice, IOCTL_START_WATCH_DEVICE, deviceId, sizeof(deviceId), NULL, 0, &dwWaitResult, 0);


	CloseHandle(hDevice);
}

void DeviceInformation::StopListen()
{
	DWORD dwWaitResult;
	HANDLE hDevice = CreateFile(CONTROL_DEVICE_DOS_NAME, 0, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);

	if(hDevice == INVALID_HANDLE_VALUE)
	{
		cout<<"INAVALID_HANDLE_FILE::startListen";
	}

	DeviceIoControl(hDevice, IOCTL_STOP_WATCH_DEVICE, deviceId, sizeof(deviceId), NULL, 0, &dwWaitResult, 0);

	CloseHandle(hDevice);
}


std::string DeviceInformation::WcharToString(WCHAR *wchar, int size)
{
	ostringstream stm;
	int i;
	for (i=0; i<size; ++i)
	{
		stm << (char)wchar[i];
	}
	return stm.str();
}



DeviceInformation::~DeviceInformation()
{

}

void MapDeviceVidsPids(const char *filename)
{
	ifstream infile(filename);	
	ostringstream tmpStream;
	char tmpLine[200];
	string tmpVid, tmpPid;

	if(infile.fail())
		return;

	while (!infile.eof() && !infile.fail())
	{
		infile >> tmpVid;
		infile.get();
		infile.getline(tmpLine, 200);
		tmpStream << tmpLine;

		VID_MAP[tmpVid] = tmpStream.str();
		tmpStream.str("");

		while(infile.get() == '\t')
		{
			infile >> tmpPid;
			infile.get();
			infile.getline(tmpLine, 200);

			tmpStream << tmpLine;

			PID_MAP[tmpVid+tmpPid] = tmpStream.str();
			tmpStream.str("");
		}
		infile.unget();
	}
}